//---------------------------------------------------------------------------------------------------
template <class Real>
Vector3<Real>::Vector3 ()
{
    // uninitialized for performance in array construction
}

//---------------------------------------------------------------------------------------------------
template <class Real>
Vector3<Real>::Vector3(Real fX, Real fY, Real fZ)
{
	m_afTuple[0] = fX;
	m_afTuple[1] = fY;
	m_afTuple[2] = fZ;
}
//---------------------------------------------------------------------------------------------------
template <class Real>
Vector3<Real>::Vector3(const Real* afTuple)
{
	m_afTuple[0] = afTuple[0];
	m_afTuple[1] = afTuple[1];
	m_afTuple[2] = afTuple[2];
}
//---------------------------------------------------------------------------------------------------
template <class Real>
Vector3<Real>::Vector3(const Vector3& rkVector3)
{
	m_afTuple[0] = rkVector3.m_afTuple[0];
	m_afTuple[1] = rkVector3.m_afTuple[1];
	m_afTuple[2] = rkVector3.m_afTuple[2];
}
//---------------------------------------------------------------------------------------------------
template <class Real>
int Vector3<Real>::CompareArrays(const Vector3& rkV) const
{
	return memcmp(m_afTuple, rkV.m_afTuple, 3*sizeof(Real));
}
//---------------------------------------------------------------------------------------------------
template <class Real>
bool Vector3<Real>::operator== (const Vector3& rkV) const
{
	return CompareArrays(rkV) == 0;
}
//---------------------------------------------------------------------------------------------------
template <class Real>
bool Vector3<Real>::operator!= (const Vector3& rkV) const
{
	return CompareArrays(rkV) != 0;
}
//---------------------------------------------------------------------------------------------------
template <class Real>
bool Vector3<Real>::operator< (const Vector3& rkV) const
{
	return CompareArrays(rkV) < 0;
}
//---------------------------------------------------------------------------------------------------
template <class Real>
bool Vector3<Real>::operator<= (const Vector3& rkV) const
{
	return CompareArrays(rkV) <= 0;
}
//---------------------------------------------------------------------------------------------------
template <class Real>
bool Vector3<Real>::operator> (const Vector3& rkV) const
{
	return CompareArrays(rkV) > 0;
}
//---------------------------------------------------------------------------------------------------
template <class Real>
bool Vector3<Real>::operator>= (const Vector3& rkV) const
{
	return CompareArrays(rkV) >= 0;
}
//---------------------------------------------------------------------------------------------------
template <class Real>
void Vector3<Real>::OrthoNomalize(Vector3& rkU, Vector3& rkV, Vector3& rkW)
{
	// r0
	rkU.Normalize();

	// r1
	Real fDot0 = rkV.Dot(rkU);
	rkV -= fDot0 * rkU;
	rkV.Normalize();

	// r2
	fDot0 = rkW.Dot(rkU);
	Real fDot1 = rkW.Dot(rkV);
	rkW -= fDot0*rkU + fDot1*rkV;
	rkW.Normalize();
}
//---------------------------------------------------------------------------------------------------
template <class Real>
void Vector3<Real>::Print()
{
	printf("%6f, %6f, %6f\n",m_afTuple[0],m_afTuple[1],m_afTuple[2]);
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Vector3<Real>::operator Real* ()
{
	return m_afTuple;
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Vector3<Real>::operator const Real* () const
{
	return m_afTuple;
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Real Vector3<Real>::operator[] (int i) const
{
	if (i < 0)
	{
		i = 0;
	}
	if (i > 2)
	{
		i = 2;
	}
	return m_afTuple[i];
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Real& Vector3<Real>::operator[] (int i)
{
	if (i < 0)
	{
		i = 0;
	}
	if (i > 2)
	{
		i = 2;
	}
	return m_afTuple[i];
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Real Vector3<Real>::X() const
{
	return m_afTuple[0];
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Real& Vector3<Real>::X()
{
	return m_afTuple[0];
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Real Vector3<Real>::Y() const
{
	return m_afTuple[1];
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Real& Vector3<Real>::Y()
{
	return m_afTuple[1];
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Real Vector3<Real>::Z() const
{
	return m_afTuple[2];
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Real& Vector3<Real>::Z()
{
	return m_afTuple[2];
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Vector3<Real>& Vector3<Real>::operator= (const Vector3& rkV)
{
	m_afTuple[0] = rkV.m_afTuple[0];
	m_afTuple[1] = rkV.m_afTuple[1];
	m_afTuple[2] = rkV.m_afTuple[2];
	return *this;
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Vector3<Real> Vector3<Real>::operator+ (const Vector3& rkV) const
{
	return Vector3(
		m_afTuple[0] + rkV.m_afTuple[0],
		m_afTuple[1] + rkV.m_afTuple[1],
		m_afTuple[2] + rkV.m_afTuple[2]);
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Vector3<Real> Vector3<Real>::operator- (const Vector3& rkV) const
{
	return Vector3(
		m_afTuple[0] - rkV.m_afTuple[0],
		m_afTuple[1] - rkV.m_afTuple[1],
		m_afTuple[2] - rkV.m_afTuple[2]);
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Vector3<Real> Vector3<Real>::operator* (const Real fScalar) const
{
	return Vector3(
		m_afTuple[0] * fScalar,
		m_afTuple[1] * fScalar,
		m_afTuple[2] * fScalar);
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Vector3<Real> operator* (Real fScalar, const Vector3<Real>& rkV)
{
	return Vector3<Real>(
		fScalar * rkV[0],
		fScalar * rkV[1],
		fScalar * rkV[2]);
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Vector3<Real> Vector3<Real>::operator/ (const Real fScalar) const
{
	Vector3<Real> kOut;
	if (fScalar != (Real)0.0)
	{
		Real fInv = (Real)1.0 / fScalar;
		kOut.m_afTuple[0] = m_afTuple[0] * fInv;
		kOut.m_afTuple[1] = m_afTuple[1] * fInv;
		kOut.m_afTuple[2] = m_afTuple[2] * fInv;
	}
	else
	{
		kOut.m_afTuple[0] = FLT_MAX;
		kOut.m_afTuple[1] = FLT_MAX;
		kOut.m_afTuple[2] = FLT_MAX;
	}
	return kOut;
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Vector3<Real> Vector3<Real>::operator- () const
{
	return Vector3(
		-m_afTuple[0],
		-m_afTuple[1],
		-m_afTuple[2]);
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Vector3<Real>& Vector3<Real>::operator += (const Vector3& rkV)
{
	m_afTuple[0] += rkV.m_afTuple[0];
	m_afTuple[1] += rkV.m_afTuple[1];
	m_afTuple[2] += rkV.m_afTuple[2];
	return *this;
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Vector3<Real>& Vector3<Real>::operator -= (const Vector3& rkV)
{
	m_afTuple[0] -= rkV.m_afTuple[0];
	m_afTuple[1] -= rkV.m_afTuple[1];
	m_afTuple[2] -= rkV.m_afTuple[2];
	return *this;
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Vector3<Real>& Vector3<Real>::operator *= (Real fScalar)
{
	m_afTuple[0] *= fScalar;
	m_afTuple[1] *= fScalar;
	m_afTuple[2] *= fScalar;
	return *this;
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Vector3<Real>& Vector3<Real>::operator /= (Real fScalar)
{
	if (fScalar != (Real)0.0)
	{
		Real fInv = (Real)1.0 / fScalar;
		m_afTuple[0] *= fInv;
		m_afTuple[1] *= fInv;
		m_afTuple[2] *= fInv;
	}
	else
	{
		m_afTuple[0] = FLT_MAX;
		m_afTuple[1] = FLT_MAX;
		m_afTuple[2] = FLT_MAX;
	}
	return *this;
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Real Vector3<Real>::Length() const
{
	return (Real)sqrt(
		m_afTuple[0]*m_afTuple[0] +
		m_afTuple[1]*m_afTuple[1] +
		m_afTuple[2]*m_afTuple[2]);
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Real Vector3<Real>::SquaredLength() const
{
	return (		
			m_afTuple[0]*m_afTuple[0] +
			m_afTuple[1]*m_afTuple[1] +
			m_afTuple[2]*m_afTuple[2]
			);
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Real Vector3<Real>::Dot(const Vector3& rkV) const
{
	return (
		m_afTuple[0]*rkV.m_afTuple[0] +
		m_afTuple[1]*rkV.m_afTuple[1] +
		m_afTuple[2]*rkV.m_afTuple[2]
		);
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Real Vector3<Real>::Normalize()
{
	Real fLength = Length();
	if (fLength > Math<Real>::ZERO_TOLERANCE)
	{
		Real fInv = (Real)1.0 / fLength;
		m_afTuple[0] *= fInv;
		m_afTuple[1] *= fInv;
		m_afTuple[2] *= fInv;
	}
	else
	{
		fLength = (Real)0.0;
		m_afTuple[0] = (Real)0.0;
		m_afTuple[1] = (Real)0.0;
		m_afTuple[2] = (Real)0.0;
	}

	return fLength;
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline Vector3<Real> Vector3<Real>::Cross(const Vector3& rkV) const
{
	return Vector3(
		m_afTuple[1]*rkV.m_afTuple[2] - m_afTuple[2]*rkV.m_afTuple[1],
		m_afTuple[2]*rkV.m_afTuple[0] - m_afTuple[0]*rkV.m_afTuple[2],
		m_afTuple[0]*rkV.m_afTuple[1] - m_afTuple[1]*rkV.m_afTuple[0]);
}
//---------------------------------------------------------------------------------------------------
template <class Real>
inline bool Vector3<Real>::SameAs(const Vector3& rkV) const
{
	Real e = (Real)0.0001;
	if ((Real)fabs(m_afTuple[0] - rkV.X()) < e
		&& (Real)fabs(m_afTuple[1] - rkV.Y()) < e
		&& (Real)fabs(m_afTuple[2] - rkV.Z()) < e)
	{
		return true;
	}
	return false;
}
//---------------------------------------------------------------------------------------------------
template <class Real>
void Vector3<Real>::GenerateOrthonormalBasis (Vector3& rkU, Vector3& rkV,
    Vector3& rkW)
{
    rkW.Normalize();
    GenerateComplementBasis(rkU,rkV,rkW);
}
//---------------------------------------------------------------------------------------------------
template <class Real>
void Vector3<Real>::GenerateComplementBasis (Vector3& rkU, Vector3& rkV,
    const Vector3& rkW)
{
    Real fInvLength;

    if (Math<Real>::FAbs(rkW.m_afTuple[0]) >=
        Math<Real>::FAbs(rkW.m_afTuple[1]) )
    {
        // W.x or W.z is the largest magnitude component, swap them
        fInvLength = Math<Real>::InvSqrt(rkW.m_afTuple[0]*rkW.m_afTuple[0] +
            rkW.m_afTuple[2]*rkW.m_afTuple[2]);
        rkU.m_afTuple[0] = -rkW.m_afTuple[2]*fInvLength;
        rkU.m_afTuple[1] = (Real)0.0;
        rkU.m_afTuple[2] = +rkW.m_afTuple[0]*fInvLength;
        rkV.m_afTuple[0] = rkW.m_afTuple[1]*rkU.m_afTuple[2];
        rkV.m_afTuple[1] = rkW.m_afTuple[2]*rkU.m_afTuple[0] -
            rkW.m_afTuple[0]*rkU.m_afTuple[2];
        rkV.m_afTuple[2] = -rkW.m_afTuple[1]*rkU.m_afTuple[0];
    }
    else
    {
        // W.y or W.z is the largest magnitude component, swap them
        fInvLength = Math<Real>::InvSqrt(rkW.m_afTuple[1]*rkW.m_afTuple[1] +
            rkW.m_afTuple[2]*rkW.m_afTuple[2]);
        rkU.m_afTuple[0] = (Real)0.0;
        rkU.m_afTuple[1] = +rkW.m_afTuple[2]*fInvLength;
        rkU.m_afTuple[2] = -rkW.m_afTuple[1]*fInvLength;
        rkV.m_afTuple[0] = rkW.m_afTuple[1]*rkU.m_afTuple[2] -
            rkW.m_afTuple[2]*rkU.m_afTuple[1];
        rkV.m_afTuple[1] = -rkW.m_afTuple[0]*rkU.m_afTuple[2];
        rkV.m_afTuple[2] = rkW.m_afTuple[0]*rkU.m_afTuple[1];
    }
}
//---------------------------------------------------------------------------------------------------
template <class Real>
void Vector3<Real>::ComputeExtremes (int iVQuantity, const Vector3* akPoint,
    Vector3& rkMin, Vector3& rkMax)
{
    assert(iVQuantity > 0 && akPoint);

    rkMin = akPoint[0];
    rkMax = rkMin;
    for (int i = 1; i < iVQuantity; i++)
    {
        const Vector3<Real>& rkPoint = akPoint[i];
        for (int j = 0; j < 3; j++)
        {
            if (rkPoint[j] < rkMin[j])
            {
                rkMin[j] = rkPoint[j];
            }
            else if (rkPoint[j] > rkMax[j])
            {
                rkMax[j] = rkPoint[j];
            }
        }
    }
}
//---------------------------------------------------------------------------------------------------